// DragDropDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DragDrop.h"
#include "DragDropDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDragDropDlg dialog

CDragDropDlg::CDragDropDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CDragDropDlg::IDD, pParent)
{
    //{{AFX_DATA_INIT(CDragDropDlg)
    //}}AFX_DATA_INIT
    // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDragDropDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(CDragDropDlg)
    DDX_Control(pDX, IDC_DROPTARGET, m_DropTarget);
    DDX_Control(pDX, IDC_TITLE2, m_Title2);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDragDropDlg, CDialog)
    //{{AFX_MSG_MAP(CDragDropDlg)
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDragDropDlg message handlers

BOOL CDragDropDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);            // Set big icon
    SetIcon(m_hIcon, FALSE);        // Set small icon
    

    m_vTree = GetDlgItem(IDC_SFTTREE1)->GetControlUnknown();
    ASSERT(m_vTree!=NULL);

    m_TitleFont.CreatePointFont(140, _T("Microsoft Sans Serif"));
    m_Title2.SetFont(&m_TitleFont);

    long i;
    i = m_vTree->Items->Add(_bstr_t(_T("Item 0")));
    i = m_vTree->Items->Add(_bstr_t(_T("Item 1")));
     m_vTree->Item[i]->Level = 1;
    i = m_vTree->Items->Add(_bstr_t(_T("Item 2")));
     m_vTree->Item[i]->Level = 2;
    i = m_vTree->Items->Add(_bstr_t(_T("Item 3")));
     m_vTree->Item[i]->Level = 1;
    

    m_textDropTarget.Register(&m_DropTarget); // register as a drop target

    return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDragDropDlg::OnPaint() 
{
    if (IsIconic())
    {
        CPaintDC dc(this); // device context for painting

        SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

        // Center icon in client rectangle
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();
    }
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDragDropDlg::OnQueryDragIcon()
{
    return (HCURSOR) m_hIcon;
}

void CDragDropDlg::OnOLEStartDragSftTree1(LPDISPATCH FAR* Data, long FAR* AllowedEffects) 
{
    IVDMDataObjectPtr pDataObject = *Data;
    ASSERT(pDataObject != NULL);

    long curr = m_vTree->Items->Current;
    // cell text
    pDataObject->SetData(_variant_t(m_vTree->Cell[curr][0]->Text), _variant_t((short)sftCFText));
    // item picture
    if (m_vTree->Item[curr]->Image->Type == sftTypeIDispatch) {
        pDataObject->SetData(_variant_t(m_vTree->Item[curr]->Image->GetPicture(), _variant_t((short)sftCFDIB)));
    } else {
        if (m_vTree->Item[curr]->Expanded != VARIANT_FALSE) 
            pDataObject->SetData(_variant_t(m_vTree->Items->ItemImageExpanded->GetPicture(), _variant_t((short)sftCFDIB)));
        else if (m_vTree->Item[curr]->DependentAllCount > 0)
            pDataObject->SetData(_variant_t(m_vTree->Items->ItemImageExpandable->GetPicture(), _variant_t((short)sftCFDIB)));
        else
            pDataObject->SetData(_variant_t(m_vTree->Items->ItemImageLeaf->GetPicture(), _variant_t((short)sftCFDIB)));
    }
}

void CDragDropDlg::OnOLEDragDropSftTree(LPDISPATCH FAR* Data, long FAR* Effect, short FAR* Button, short FAR* Shift, float FAR* x, float FAR* y) 
{
    IVDMDataObjectPtr pDataObject = *Data;
    ASSERT(pDataObject != NULL);

    // get horizontal extent and width of column 0
    long horzExtent = m_vTree->Items->HorizontalExtentPix;
    long col0Width = m_vTree->Column[0]->WidthPix;
    
    long insertAt = m_vTree->Items->DropHighlight;
    if (insertAt < 0) return;

    if (pDataObject->GetFormat(sftCFText) != VARIANT_FALSE) {
        int lvl = m_vTree->Item[insertAt]->Level;
        _variant_t object = pDataObject->GetData((short)sftCFText);
        _bstr_t astring = object;
        long newItem = m_vTree->Items->Insert(insertAt + 1, astring);
        m_vTree->Item[newItem]->Level = lvl + 1;
    } else if (pDataObject->GetFormat(sftCFDIB)) {
        _variant_t object = pDataObject->GetData((short)sftCFDIB);
        IPictureDispPtr pPicDisp = object;
        m_vTree->Cell[insertAt][0]->Image->PutRefPicture(pPicDisp);
        m_vTree->Cell[insertAt][0]->ImageHAlign = halignSftTreeRight;
    } else if (pDataObject->GetFormat(sftCFFiles)) {
        m_vTree->BulkUpdate = VARIANT_true;
        int lvl = m_vTree->Item[insertAt]->Level;
        long newItem = insertAt + 1;
        for (int i = pDataObject->Files->Count ; i >= 1 ; --i) {
            newItem = m_vTree->Items->Insert(newItem, pDataObject->Files->GetItem(i));
            m_vTree->Item[newItem]->Level = lvl + 1;
        }
        m_vTree->BulkUpdate = VARIANT_FALSE;
    }
    
    // make horizontal extent and width of column 0 wider than previous
    // setting, but never smaller
    m_vTree->ColumnsObj->MakeOptimal();
    m_vTree->Items->RecalcHorizontalExtent();
    
    if (horzExtent > m_vTree->Items->HorizontalExtentPix)
        m_vTree->Items->HorizontalExtentPix = horzExtent;
    if (col0Width > m_vTree->Column[0]->WidthPix)
        m_vTree->Column[0]->WidthPix = col0Width;
}


/* DropTarget - Text Box Implementation */

DROPEFFECT CTextDropTarget::OnDragEnter( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
    return DROPEFFECT_COPY;
}

DROPEFFECT CTextDropTarget::OnDragOver( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )
{
    if (pDataObject->IsDataAvailable(CF_TEXT))
        return DROPEFFECT_COPY;
    return DROPEFFECT_NONE;
}

void CTextDropTarget::OnDragLeave( CWnd* pWnd )
{
}

DROPEFFECT CTextDropTarget::OnDropEx( CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point )
{
    if (!pWnd->IsKindOf(RUNTIME_CLASS(CEdit)))
        return DROPEFFECT_NONE;
    CEdit* pDropTargetControl = (CEdit*) pWnd;

    // extract the data that arrived here.  This is just a sample
    // and is very application specific.
    CFile*pFile = pDataObject->GetFileData(CF_TEXT, NULL);
    if (pFile) {
        // the data is in CF_TEXT format, just add the text as a new item at
        // the insertion point
        TCHAR szBuffer[256];
        pFile->Read(szBuffer, sizeof(szBuffer)/sizeof(TCHAR));

        pDropTargetControl->SetWindowText(szBuffer);

        delete pFile;
    }
    return DROPEFFECT_COPY;
}

BEGIN_EVENTSINK_MAP(CDragDropDlg, CDialog)
    //{{AFX_EVENTSINK_MAP(CDragDropDlg)
    ON_EVENT(CDragDropDlg, IDC_SFTTREE1, 24 /* OLEStartDrag */, OnOLEStartDragSftTree1, VTS_PDISPATCH VTS_PI4)
    ON_EVENT(CDragDropDlg, IDC_SFTTREE1, 23 /* OLEDragDrop */, OnOLEDragDropSftTree, VTS_PDISPATCH VTS_PI4 VTS_PI2 VTS_PI2 VTS_PR4 VTS_PR4)
    //}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()